package com.fengke.portal.action.payment;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.xml.parsers.ParserConfigurationException;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.xml.sax.SAXException;

import com.fengke.dao.model.OrderModel;
import com.fengke.dao.model.PaymentModel;
import com.fengke.payment.alipay.config.AlipayConfig;
import com.fengke.payment.alipay.util.AlipayNotify;
import com.fengke.payment.tencent.common.Signature;
import com.fengke.payment.tencent.common.XMLParser;
import com.fengke.portal.action.BaseAction;
import com.fengke.service.OrderService;
import com.fengke.service.vo.OrderVO;
import com.fengke.service.vo.PaymentVO;
import com.fengke.util.Constants;
import com.fengke.util.LoggerFactory;
import com.fengke.util.StringUtil;

/**
 * 微信端支付Action 1、接收微信支付异步通知
 * 
 * @author Administrator
 * 
 */
public class PaymentAction extends BaseAction {
	private static final long serialVersionUID = -7491014543153775507L;
	private Logger logger = LoggerFactory.getLogger(PaymentAction.class);
	private OrderService orderService;
	private OrderVO orderVO;
	private PaymentVO paymentVO;

	/**
	 * 接收微信支付异步通知，进行订单状态同步
	 * 
	 * @return
	 */
	public String asyncTecentNotify() {
		logger.info("asyncTecentNotify Start  .... ");
		InputStream inStream = null;
		ByteArrayOutputStream outSteam = null;
		boolean isSuccess = true;
		try {
			inStream = this.getRequest().getInputStream();
			outSteam = new ByteArrayOutputStream();
			byte[] buffer = new byte[1024];
			int len = 0;
			while ((len = inStream.read(buffer)) != -1) {
				outSteam.write(buffer, 0, len);
			}
			String result = new String(outSteam.toByteArray(), "utf-8");
			logger.info("asyncTecentNotify !result=" + result);
			if(!StringUtil.isEmpty(result)) {
				// 验证签名
				if(Signature.checkIsSignValidFromResponseString(result)) {
					Map<String, Object> map = XMLParser.getMapFromXML(result);
					if(map != null && map.size() > 0) {
						String out_trade_no = (String) map.get("out_trade_no");
						String result_code = (String) map.get("result_code");
						orderVO = new OrderVO();
						orderVO.setOrderModel(new OrderModel());
						orderVO.getOrderModel().setSn(out_trade_no);
						orderVO = orderService.researchOrderById(orderVO);
						if(orderVO != null && orderVO.getOrderModel() != null) {
							paymentVO = new PaymentVO();
							paymentVO.setPaymentModel(new PaymentModel());
							paymentVO.getPaymentModel().setOrder(orderVO.getOrderModel());
							paymentVO = orderService.researchPaymentVOById(paymentVO);
							if("SUCCESS".equals(result_code)) {
								// 成功
								if(!OrderModel.PaymentStatus.paid.equals(orderVO.getOrderModel().getPaymentStatus())) {
									orderVO.getOrderModel().setPaymentStatus(OrderModel.PaymentStatus.paid);
									orderService.updatePaymentVOStatus(paymentVO);
								}
								if(!PaymentModel.Status.success.equals(paymentVO.getPaymentModel().getStatus())) {
									paymentVO.getPaymentModel().setStatus(PaymentModel.Status.success);
									orderService.updateOrderVOPaymentStatus(orderVO);
								}
							} else {
								// 失败
								if(!PaymentModel.Status.failure.equals(paymentVO.getPaymentModel().getStatus())) {
									paymentVO.getPaymentModel().setStatus(PaymentModel.Status.failure);
									orderService.updatePaymentVOStatus(paymentVO);
								}
							}
						} else {
							// 获取订单失败
							isSuccess = false;
						}
					} else {
						// 参数列表为空
						isSuccess = false;
					}
				} else {
					// 签名验证失败
					isSuccess = false;
				}
			} else {
				// 返回结果为空！
				isSuccess = false;
			}
			
		} catch (IOException e) {
			logger.error("asyncTecentNotify IOException! order.sn" + orderVO.getOrderModel().getSn(), e);
		} catch (ParserConfigurationException e) {
			logger.error("asyncTecentNotify ParserConfigurationException! order.sn" + orderVO.getOrderModel().getSn(), e);
			isSuccess = false;
		} catch (SAXException e) {
			logger.error("asyncTecentNotify SAXException! order.sn" + orderVO.getOrderModel().getSn(), e);
			isSuccess = false;
		} catch (Exception e) {
			logger.error("asyncTecentNotify Exception! order.sn" + orderVO.getOrderModel().getSn(), e);
			isSuccess = false;
		} finally {
			try {
				if (outSteam != null) {
					outSteam.close();
				}
			} catch (IOException e) {
				logger.error("asyncTecentNotify IOException! order.sn" + orderVO.getOrderModel().getSn(), e);
			} finally {
				try {
					if(inStream != null) {
						inStream.close();
					}
				} catch (IOException e) {
					logger.error("asyncTecentNotify IOException! order.sn" + orderVO.getOrderModel().getSn(), e);
				}
			}
		}
		StringBuilder sbXml = new StringBuilder();
		if(isSuccess) {
			// 成功
			sbXml.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
			.append("<xml>")
			.append("<return_code><![CDATA[SUCCESS]]></return_code>")
			.append("<return_msg><![CDATA[OK]]></return_msg>")
			.append("</xml");
		} else {
			// 失败
			sbXml.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
			.append("<xml>")
			.append("<return_code><![CDATA[FAIL]]></return_code>")
			.append("<return_msg>参数格式校验错误</return_msg>")
			.append("</xml");
		}
		getResponse().setCharacterEncoding("UTF-8");
		getResponse().setContentType("text/xml");
		try {
			getResponse().getWriter().print(sbXml.toString());
		} catch (IOException e) {
			logger.error("Response XML报文时出错！", e);
		}
		return null;
	}
	/**
	 * 微信支付同步通知接口
	 * @return
	 */
	public String syncTencentNotify() {
		// get_brand_wcpay_request:cancel 用户取消
		// get_brand_wcpay_request:fail 发送失败
		// get_brand_wcpay_request:ok //发送成功
		// WeixinJSBridge.log(res.err_msg);alert(res);
		// alert(res.err_code + res.err_desc);
		// alert(res.err_msg);
		if(orderVO == null || orderVO.getOrderModel() == null || orderVO.getOrderModel().getSn() == null) {
			return Constants.ActionReturnName.ERROR;
		}
		// 获取参数
		String return_json = this.getRequest().getParameter("return_json");
		String return_code = this.getRequest().getParameter("return_code");
		String return_desc = this.getRequest().getParameter("return_desc");
		String return_message = this.getRequest().getParameter("return_message");
		String order_sn = orderVO.getOrderModel().getSn();
		logger.info("syncTencentNotify... sn=" + orderVO.getOrderModel().getSn() + ", return_message" + return_message + ", return_json=" + return_json + ", return_code" + return_code + ", return_desc" + return_desc);
		if("get_brand_wcpay_request:ok".equals(return_message)) {
			// 发送成功
			try {
				orderVO = orderService.researchOrderById(orderVO);
			} catch (Exception e) {
				logger.error("syncTencentNotify researchOrderById Exception! orderVO=" + orderVO, e);
			}
			if(orderVO != null && orderVO.getOrderModel() != null) {
				paymentVO = new PaymentVO();
				paymentVO.setPaymentModel(new PaymentModel());
				paymentVO.getPaymentModel().setOrder(orderVO.getOrderModel());
				try {
					paymentVO = orderService.researchPaymentVOById(paymentVO);
				} catch (Exception e) {
					logger.error("syncTencentNotify researchPaymentVOById Exception! paymentVO=" + paymentVO, e);
				}
				if(!OrderModel.PaymentStatus.paid.equals(orderVO.getOrderModel().getPaymentStatus())) {
					orderVO.getOrderModel().setPaymentStatus(OrderModel.PaymentStatus.paid);
					try {
						orderService.updateOrderVOPaymentStatus(orderVO);
					} catch (Exception e) {
						logger.error("syncTencentNotify updateOrderVOPaymentStatus Exception! orderVO=" + orderVO, e);
					}
				}
				if(paymentVO != null && paymentVO.getPaymentModel() != null) {
					if(!PaymentModel.Status.success.equals(paymentVO.getPaymentModel().getStatus())) {
						paymentVO.getPaymentModel().setStatus(PaymentModel.Status.success);
						try {
							orderService.updatePaymentVOStatus(paymentVO);
						} catch (Exception e) {
							logger.error("syncTencentNotify updatePaymentVOStatus Exception! paymentVO=" + paymentVO, e);
						}
					}
				}
			} else {
				logger.error("syncTencentNotify 根据order_sn=" + order_sn + "未能找到订单!");
			}
		} else if("get_brand_wcpay_request:cancel".equals(return_message)) {
			// 用户取消
		} else if("get_brand_wcpay_request:fail".equals(return_message)) {
			// 发送失败
		}
		
		return Constants.ActionReturnName.SUCCESS;
	}
	
	/**
	 * 支付宝支付，异步通知
	 * 
	 * @return
	 */
	public String asyncAliNotify() {
		boolean isSuccess = true;
		//获取支付宝POST过来反馈信息
		Map<String, String> params = new HashMap<String, String>();
		@SuppressWarnings("unchecked")
		Map<String, Object> requestParams = this.getRequest().getParameterMap();
		for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
			String name = iter.next();
			String[] values = (String[]) requestParams.get(name);
			String valueStr = "";
			for (int i = 0; i < values.length; i++) {
				valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
			}
			//乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
			//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
			params.put(name, valueStr);
		}
		//获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
		logger.info("asyncAliNotify params=" + params);
		//RSA签名解密
	   	if(AlipayConfig.sign_type.equals("0001")) {
	   		try {
				params = AlipayNotify.decrypt(params);
			} catch (Exception e) {
				logger.error("asyncAliNotify AlipayNotify.decrypt Exception! params=" + params, e);
			}
	   	}
		//XML解析notify_data数据
		Document doc_notify_data = null;
		try {
			doc_notify_data = DocumentHelper.parseText(params.get("notify_data"));
		} catch (DocumentException e) {
			logger.error("asyncAliNotify DocumentHelper.parseText Exception! params=" + params, e);
		}
		
		//商户订单号
		String out_trade_no = doc_notify_data.selectSingleNode( "//notify/out_trade_no" ).getText();

		//支付宝交易号
		String trade_no = doc_notify_data.selectSingleNode( "//notify/trade_no" ).getText();

		//交易状态
		String trade_status = doc_notify_data.selectSingleNode( "//notify/trade_status" ).getText();

		//获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
		try {
			if(AlipayNotify.verifyNotify(params)){
				//验证成功
				//////////////////////////////////////////////////////////////////////////////////////////
				logger.info("AlipayNotify.verifyNotify 通过! out_trade_no=" + out_trade_no + ", trade_status=" + trade_status + ", trade_no=" + trade_no);
				orderVO = new OrderVO();
				orderVO.setOrderModel(new OrderModel());
				orderVO.getOrderModel().setSn(out_trade_no);
				orderVO = orderService.researchOrderById(orderVO);
				if(orderVO != null && orderVO.getOrderModel() != null) {
					paymentVO = new PaymentVO();
					paymentVO.setPaymentModel(new PaymentModel());
					paymentVO.getPaymentModel().setOrder(orderVO.getOrderModel());
					paymentVO = orderService.researchPaymentVOById(paymentVO);
					if(trade_status.equals("TRADE_FINISHED")){
						//判断该笔订单是否在商户网站中已经做过处理
						//如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
						//如果有做过处理，不执行商户的业务程序
						if(!OrderModel.PaymentStatus.paid.equals(orderVO.getOrderModel().getPaymentStatus())) {
							orderVO.getOrderModel().setPaymentStatus(OrderModel.PaymentStatus.paid);
							orderService.updateOrderVOPaymentStatus(orderVO);
						}
						if(paymentVO != null && paymentVO.getPaymentModel() != null) {
							if(!PaymentModel.Status.success.equals(paymentVO.getPaymentModel().getStatus())) {
								paymentVO.getPaymentModel().setStatus(PaymentModel.Status.success);
								orderService.updatePaymentVOStatus(paymentVO);
							}
						}
						//注意：
						//该种交易状态只在两种情况下出现
						//1、开通了普通即时到账，买家付款成功后。
						//2、开通了高级即时到账，从该笔交易成功时间算起，过了签约时的可退款时限（如：三个月以内可退款、一年以内可退款等）后。
					} else if (trade_status.equals("TRADE_SUCCESS")){
						//判断该笔订单是否在商户网站中已经做过处理
						//如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
						//如果有做过处理，不执行商户的业务程序
						if(!OrderModel.PaymentStatus.paid.equals(orderVO.getOrderModel().getPaymentStatus())) {
							orderVO.getOrderModel().setPaymentStatus(OrderModel.PaymentStatus.paid);
							orderService.updateOrderVOPaymentStatus(orderVO);
						}
						if(paymentVO != null && paymentVO.getPaymentModel() != null) {
							if(!PaymentModel.Status.success.equals(paymentVO.getPaymentModel().getStatus())) {
								paymentVO.getPaymentModel().setStatus(PaymentModel.Status.success);
								orderService.updatePaymentVOStatus(paymentVO);
							}
						}
						//注意：
						//该种交易状态只在一种情况下出现——开通了高级即时到账，买家付款成功后。
					} else if (trade_status.equals("WAIT_BUYER_PAY")) {
						// 交易创建，等待买家付款。
					} else if (trade_status.equals("TRADE_CLOSED")) {
						// 在指定时间段内未支付时关闭的交易；
						// 在交易完成全额退款成功时关闭的交易。
					} else if (trade_status.equals("TRADE_PENDING")) {
						// 等待卖家收款（买家付款后，如果卖家账号被冻结）。
					}
				} else {
					// 获取订单失败
					isSuccess = false;
				}

				isSuccess = true;
				//////////////////////////////////////////////////////////////////////////////////////////
			} else {//验证失败
				logger.error("asyncAliNotify 支付宝异步消息验证失败！params=" + params);
				isSuccess = false;
			}
		} catch (Exception e) {
			logger.error("asyncAliNotify AlipayNotify.verifyNotify Exception!params=" + params, e);
		}
		
		String returnStr = null;
		if(isSuccess) {
			returnStr = "success";
		} else {
			returnStr = "fail";
		}
		try {
			getResponse().getWriter().print(returnStr);
		} catch (IOException e) {
			logger.error("asyncAliNotify Response 时出错！returnStr=" + returnStr, e);
		}
		return null;
	}
	
	/**
	 * 支付宝支付，同步通知
	 * 
	 * @return
	 */
	public String syncAliNotify() {
		//获取支付宝GET过来反馈信息
		Map<String,String> params = new HashMap<String,String>();
		@SuppressWarnings("unchecked")
		Map<String, Object> requestParams = this.getRequest().getParameterMap();
		for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
			String name = (String) iter.next();
			String[] values = (String[]) requestParams.get(name);
			String valueStr = "";
			for (int i = 0; i < values.length; i++) {
				valueStr = (i == values.length - 1) ? valueStr + values[i]
						: valueStr + values[i] + ",";
			}
			//乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
			try {
				valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
			} catch (UnsupportedEncodingException e) {
				logger.error("syncAliNotify valueStr.getBytes Exception! valueStr=" + valueStr, e);
			}
			params.put(name, valueStr);
		}
		logger.info("asyncAliNotify params=" + params);
		//获取支付宝的通知返回参数
		//商户订单号
		String out_trade_no = null;
		try {
			out_trade_no = new String(this.getRequest().getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
		} catch (UnsupportedEncodingException e) {
			logger.error("syncAliNotify get out_trade_no Exception!", e);
		}

		//支付宝交易号
		String trade_no = null;
		try {
			trade_no = new String(this.getRequest().getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");
		} catch (UnsupportedEncodingException e) {
			logger.error("syncAliNotify get trade_no Exception!", e);
		}

		//交易状态
		String result = null;
		try {
			result = new String(this.getRequest().getParameter("result").getBytes("ISO-8859-1"),"UTF-8");
		} catch (UnsupportedEncodingException e) {
			logger.error("syncAliNotify get result Exception!", e);
		}
		if(StringUtil.isEmpty(out_trade_no) || StringUtil.isEmpty(trade_no) || StringUtil.isEmpty(result)) {
			this.addPageDangerMessage("获取支付宝的通知返回参数失败！");
		} else {
			//计算得出通知验证结果
			boolean verify_result = AlipayNotify.verifyReturn(params);
			
			if(verify_result){//验证成功
				logger.info("syncAliNotify AlipayNotify.verifyReturn 通过! out_trade_no=" + out_trade_no + ", result=" + result + ", trade_no=" + trade_no);
				//////////////////////////////////////////////////////////////////////////////////////////
				//判断该笔订单是否在商户网站中已经做过处理
				//如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
				//如果有做过处理，不执行商户的业务程序
				orderVO = new OrderVO();
				orderVO.setOrderModel(new OrderModel());
				orderVO.getOrderModel().setSn(out_trade_no);
				try {
					orderVO = orderService.researchOrderById(orderVO);
				} catch (Exception e) {
					logger.error("syncAliNotify researchOrderById Exception! orderVO=" + orderVO, e);
				}
				if(orderVO != null && orderVO.getOrderModel() != null) {
					paymentVO = new PaymentVO();
					paymentVO.setPaymentModel(new PaymentModel());
					paymentVO.getPaymentModel().setOrder(orderVO.getOrderModel());
					try {
						paymentVO = orderService.researchPaymentVOById(paymentVO);
					} catch (Exception e) {
						logger.error("syncAliNotify researchPaymentVOById Exception! paymentVO=" + paymentVO, e);
					}
					if(!OrderModel.PaymentStatus.paid.equals(orderVO.getOrderModel().getPaymentStatus())) {
						orderVO.getOrderModel().setPaymentStatus(OrderModel.PaymentStatus.paid);
						try {
							orderService.updateOrderVOPaymentStatus(orderVO);
						} catch (Exception e) {
							logger.error("syncAliNotify updateOrderVOPaymentStatus Exception! orderVO=" + orderVO, e);
						}
					}
					if(paymentVO != null && paymentVO.getPaymentModel() != null) {
						if(!PaymentModel.Status.success.equals(paymentVO.getPaymentModel().getStatus())) {
							paymentVO.getPaymentModel().setStatus(PaymentModel.Status.success);
							try {
								orderService.updatePaymentVOStatus(paymentVO);
							} catch (Exception e) {
								logger.error("syncAliNotify updatePaymentVOStatus Exception! paymentVO=" + paymentVO, e);
							}
						}
					}
				}
				//////////////////////////////////////////////////////////////////////////////////////////
			}else{
				//该页面可做页面美工编辑
				logger.info("syncAliNotify AlipayNotify.verifyReturn 验证失败 params=" + params);
			}
		}
		return Constants.ActionReturnName.SUCCESS;
	}
	
	public OrderVO getOrderVO() {
		return orderVO;
	}

	public void setOrderVO(OrderVO orderVO) {
		this.orderVO = orderVO;
	}

	public PaymentVO getPaymentVO() {
		return paymentVO;
	}

	public void setPaymentVO(PaymentVO paymentVO) {
		this.paymentVO = paymentVO;
	}

	public OrderService getOrderService() {
		return orderService;
	}

	public void setOrderService(OrderService orderService) {
		this.orderService = orderService;
	}
}
